﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SceneLib;

namespace OpenGL
{
    class PerlingNoise
    {
        private int seed;
        private Vector color1;
        private Vector color2;

        public PerlingNoise(Vector c1, Vector c2)
        {
            Random rand = new Random(100);
            seed = rand.Next();
            color1 = c1.Copy();
            color2 = c2.Copy();
        }

        private float InterPolation(float a, float b, float c)
        {
            return a + (b - a) * c * c * (3 - 2 * c);

        }

        private Vector InterLinear(Vector a, Vector b, float c)
        {
            return (1 - c) * a +  c * b;
        }

        private float Noise(int x)
        {
            x = (x << 13) ^ x;
            return (((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 2147483648.0f);
        }

        private float PerlinNoise(float x, float y, int width, int octaves, int seed, double periode)
        {

            float a, b, value = 0, freq, zoneX, zoneY;
            int s, box, num, stepX, stepY;
            int amplitude = 120;
            int noisedata;

            freq = 1 / (float)(periode);

            for (s = 0; s < octaves; s++)
            {
                num = (int)(width * freq);
                stepX = (int)(x * freq);
                stepY = (int)(y * freq);
                zoneX = x * freq - stepX;
                zoneY = y * freq - stepY;
                box = stepX + stepY * num;
                noisedata = (box + seed);
                a = InterPolation(Noise(noisedata), Noise(noisedata + 1), zoneX);
                b = InterPolation(Noise(noisedata + num), Noise(noisedata + 1 + num), zoneX);
                value = InterPolation(a, b, zoneY) * amplitude;

            }
            return value;
        }

        public Vector getColor(int x, int y)
        {
            int width;
            float disp1, disp2, disp3, disp4, disp5, disp6, scale;

            scale = 4.0f;
            width = 512 * 512;//1024 * 1024;
            
            disp1 = PerlinNoise(x * scale, y * scale, width, 1, seed, 100);
            disp2 = PerlinNoise(x * scale, y * scale, width, 1, seed, 25);
            disp3 = PerlinNoise(x * scale, y * scale, width, 1, seed, 12.5);
            disp4 = PerlinNoise(x * scale, y * scale, width, 1, seed, 6.25);
            disp5 = PerlinNoise(x * scale, y * scale, width, 1, seed, 3.125);
            disp6 = PerlinNoise(x * scale, y * scale, width, 1, seed, 1.56);

            return colour((int)disp1 + (int)(disp2 * .25) + (int)(disp3 * .125) + (int)(disp4 * .0625) + (int)(disp5 * .03125) + (int)(disp6 * .0156));
        }

        private Vector colour(float valor)
        {
            Vector c = InterLinear(color2, color1, valor / 256.0f);

            return c;
        }
    }
}
